<?php

// +----------------------------------------------------------------------
// | framework
// +----------------------------------------------------------------------
// | 版权所有 2014~2018 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
// +----------------------------------------------------------------------
// | 官方网站: http://framework.thinkadmin.top
// +----------------------------------------------------------------------
// | 开源协议 ( https://mit-license.org )
// +----------------------------------------------------------------------
// | github开源项目：https://github.com/zoujingli/framework
// +----------------------------------------------------------------------

namespace app\store\controller\api\member;

use app\api\controller\ApiCommon;
use app\store\controller\api\Member;
use app\store\service\Goods;
use library\tools\Data;
use think\Db;

/**
 * 订单接口管理
 * Class Order
 * @package app\store\controller\api\member
 */
class Order extends ApiCommon
{
    protected $orderTable = 'store_order';
    protected $goodsTable = 'store_goods';
    protected $couponsTable = 'lite_coupons';
    protected $recordTable = 'lite_coupons_record';

    /**
     * 创建商城订单
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * 商品ID1@商品规格1@商品数量1||商品ID2@商品规格2@商品数量2
     */
    public function set()
    {
        // 商品规则
        $data = $this->request->param();
        if (empty($data)) $this->error('下单商品不能为空！');
        // 订单处理
        list($orderList, $order) = [[], [
            'status'   => '1', 'mid' => $this->openid,
            'order_no' => Data::uniqidNumberCode(12),
            'express_address_id' =>  $data['express_address_id']
        ]];
//        var_dump($this->openid);exit;
        $goods_id = $data['productData']['id'];
        $goods_spec = $data['productData']['attr']['goods_spec'];
        $number = 1;
        // 商品信息检查
        $goods = Db::name('StoreGoods')->where(['id' => $goods_id, 'status' => '1', 'is_deleted' => '0'])->find();
        if (empty($goods)) $this->error('查询商品主体信息失败，请稍候再试！');
        $spec = Db::name('StoreGoodsList')->where(['goods_id' => $goods_id, 'goods_spec' => $goods_spec])->find();
        if (empty($spec)) $this->error('查询商品规则信息失败，请稍候再试！');
        // 商品库存检查
        if ($spec['number_sales'] + $number > $spec['number_stock']) {
            $this->error('商品库存不足，请购买其它商品！');
        }
        // 订单详情处理
        array_push($orderList, [
            'mid'               => $order['mid'],
//            'from_mid'          => $order['from_mid'],
            'order_no'          => $order['order_no'],
            // 商品信息字段管理
            'goods_id'          => $goods_id,
            'goods_spec'        => $goods_spec,
            'goods_logo'        => $goods['logo'],
            'goods_title'       => $goods['title'],
            'number_goods'      => $number,
            'number_express'    => $spec['number_express'],
            // 费用字段处理
            'price_market'      => $spec['price_market'],
            'price_selling'     => $spec['price_selling'],
            'price_real'        => $spec['price_selling'] * $number,
            'price_express'     => $goods['price_express'],
            // 返利字段处理
            'price_rate'        => $goods['price_rate'],
            'price_rate_amount' => $spec['price_selling'] * $number * $goods['price_rate'] / 100,
        ]);
        $order['price_goods'] = array_sum(array_column($orderList, 'price_real')) + 0;
        $order['price_express'] = max(array_column($orderList, 'price_express')) + 0;
        $order['price_total'] = $order['price_goods'] + $order['price_express'];
        $order['price_rate_amount'] = array_sum(array_column($orderList, 'price_rate_amount')) + 0;

        //订单地址信息
        $order['status'] = '2';
        $where = ['id' => $data['express_address_id'], 'mid' => $this->openid];
        $address = Db::name('StoreMemberAddress')->where($where)->find();
        if (empty($address)) $this->error('会员收货地址异常，请刷新页面重试！');
        $order['express_address_id'] = $data['express_address_id'];
        $order['express_name'] = $address['name'];
        $order['express_phone'] = $address['phone'];
        $order['express_province'] = $address['province'];
        $order['express_city'] = $address['city'];
        $order['express_area'] = $address['area'];
        $order['express_address'] = $address['address'];

        try {
            // 订单数据写入
            $orderId = Db::name('StoreOrder')->insertGetId($order);
            Db::name('StoreOrderList')->insertAll($orderList);
            // 同步商品库存及销量
            foreach (array_unique(array_column($orderList, 'goods_id')) as $goodsId) Goods::syncStock($goodsId);
            //，请补全收货信息后支付！
            $this->success('订单创建成功', $orderId);
        } catch (\think\exception\HttpResponseException $exception) {
            throw $exception;
        } catch (\Exception $e) {
            $this->error("创建订单失败，请稍候再试！{$e->getMessage()}");
        }
    }

    /**
     * 订单信息完成
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function perfect()
    {
        $data = $this->_input([
            'order_no'   => $this->request->post('order_no'),
            'address_id' => $this->request->post('address_id'),
        ], [
            'order_no'   => 'require',
            'address_id' => 'require',
        ], [
            'order_no.require'   => '订单号不能为空！',
            'address_id.require' => '收货地址ID不能为空（0自提可以为空）',
        ]);
        $map = ['order_no' => $data['order_no'], 'mid' => $this->member['id']];
        $order = Db::name('StoreOrder')->whereIn('status', ['1', '2'])->where($map)->find();
        if (empty($order)) $this->error('订单异常，请返回商品重新下单！');
        $update = ['status' => '2'];
        $where = ['id' => $data['address_id'], 'mid' => $this->member['id']];
        $address = Db::name('StoreMemberAddress')->where($where)->find();
        if (empty($address)) $this->error('会员收货地址异常，请刷新页面重试！');
        $update['express_address_id'] = $data['address_id'];
        $update['express_name'] = $address['name'];
        $update['express_phone'] = $address['phone'];
        $update['express_province'] = $address['province'];
        $update['express_city'] = $address['city'];
        $update['express_area'] = $address['area'];
        $update['express_address'] = $address['address'];
        if (Db::name('StoreOrder')->where($map)->update($update) !== false) {
            $params = $this->getPayParams($order['order_no'], $order['price_total']);
            $this->success('更新订单会员信息成功！', $params);
        }
        $this->error('更新订单会员信息失败，请稍候再试！');
    }

    /**
     * 获取订单支付状态
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function pay()
    {
        $order_no = $this->request->post('order_no');
        $order = Db::name('StoreOrder')->where(['order_no' => $order_no])->find();
        if (empty($order_no)) $this->error('获取订单信息异常，请稍候再试！');
        if ($order['pay_state']) $this->error('订单已经完成支付，不需要再次支付！');
        if ($order['status'] <> 2) $this->error('该订单不能发起支付哦！');
        try {
            $param = $this->getPayParams($order['order_no'], $order['price_total']);
            $this->success('获取订单支付参数成功！', $param);
        } catch (\think\exception\HttpResponseException $exception) {
            throw  $exception;
        } catch (\Exception $e) {
            $this->error("获取订单支付参数失败，{$e->getMessage()}");
        }
    }

    /**
     * 获取订单支付参数
     * @param string $order_no
     * @param string $pay_price
     * @return array
     */
    private function getPayParams($order_no, $pay_price)
    {
        $options = [
            'body'             => '商城订单支付',
            'openid'           => $this->openid,
            'out_trade_no'     => $order_no,
            // 'total_fee'        => '1',
            'total_fee'        => $pay_price * 100,
            'trade_type'       => 'JSAPI',
            'notify_url'       => url('@store/api.notify/wxpay', '', false, true),
            'spbill_create_ip' => $this->request->ip(),
        ];
        try {
            $pay = \We::WePayOrder(config('wechat.miniapp'));
            $info = $pay->create($options);
            if ($info['return_code'] === 'SUCCESS' && $info['result_code'] === 'SUCCESS') {
                return $pay->jsapiParams($info['prepay_id']);
            }
            if (isset($info['err_code_des'])) throw new \think\Exception($info['err_code_des']);
        } catch (\Exception $e) {
            $this->error("创建订单失败参数失败，{$e->getMessage()}");
        }
    }

    /**
     * 获取订单列表
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function gets()
    {
        $where = [['mid', 'eq', $this->mid]];
        if ($this->request->has('order_no', 'post', true)) {
            $where[] = ['order_no', 'eq', $this->request->post('order_no')];
        } else {
            $where[] = ['status', 'in', ['0', '2', '3', '4', '5']];
        }
        if ($this->request->has('status', 'post', true)) {
            $where[] = ['status', 'eq', $this->request->post('status')];
        }
        $result = $this->_query('StoreOrder')->where($where)->order('id desc')->page(true, false, false, 20);
        $glist = Db::name('StoreOrderList')->whereIn('order_no', array_unique(array_column($result['list'], 'order_no')))->select();
        foreach ($result['list'] as &$vo) {
            list($vo['goods_count'], $vo['list']) = [0, []];
            foreach ($glist as $goods) if ($vo['order_no'] === $goods['order_no']) {
                $vo['list'][] = $goods;
                $vo['goods_count'] += $goods['number_goods'];
            }
        }
        $this->success('获取订单列表成功！', $result);
    }

    /**
     * 获取单个订单列
     */
    public function get()
    {
        $where = ['id' => $this->request->param('orderId')];
        $result = db('StoreOrder')->where($where)->find();
        $glist = db('StoreOrderList')->where(['order_no' => $result['order_no']])->select();
        $result['list'] = $glist;
        if(isset($glist[0]['goods_id'])){
            $couponsInfo = $this->getCoupons($glist[0]['goods_id'], $result['price_total']);
            $result['couponsList'] = $couponsInfo['couponsList'];
        }
        //获取优惠劵
        $this->success('获取订单成功！', $result);
    }

    public function getCoupons($product = '', $total = 0)
    {
        $res['price'] = $total;
        //查询优惠券
        $now = date('Y-m-d H:i:s');
        $where[] = ['is_deleted' , '=', 0];
        $where[] = ['open_id' , '=', $this->openid];
        $where[] = ['status' , '=',  1];
        $where[] = ['use_type' , '=',  2]; // 活动
        $where2[] = ['use_end_time' , '>',  $now];
        $where2[] = ['use_start_time' , '<',  $now];
        $where3[] = ['limit_use_type' , '=',  3];
        $couponsList1 = db::table($this->recordTable)->where($where)->where($where2)->select();
        $couponsList2 = db::table($this->recordTable)->where($where)->where($where3)->select();
        $couponsList = array_merge($couponsList1, $couponsList2);
        $couponsIds = array_column($couponsList, 'coupons_id');
        $couponsData = db::table($this->couponsTable)->where('id', 'in', $couponsIds)->column('id, name, use_type, discount_value, activity_type, discount,meet_value,reduction,amount','id');
        foreach ($couponsList as $key => $value){
            //限制单个商品
            if(!in_array($product, explode(',', $value['product_id'])) && $value['product_id'] != -1){
                unset($couponsList[$key]);continue;
            }

            //计算折扣金额
            $coupons = $couponsData[$value['coupons_id']]; //折扣方式

            if($value['coupons_type'] == 1 && ($coupons['discount_value'] == -1 || $res['price'] >= $coupons['discount_value'])){ //优惠券1折扣券，2满x减n,3无条件立减
                $couponsList[$key]['reduced_price'] = $res['price'] * (1-$coupons['discount']/100);
            }else if($value['coupons_type'] == 2 && ($coupons['meet_value'] == -1 || $res['price'] >= $coupons['meet_value'])){
                $couponsList[$key]['reduced_price'] = $coupons['reduction'];
            }else if($value['coupons_type'] == 3){
                $couponsList[$key]['reduced_price'] = $coupons['amount'];
            }else{
                unset($couponsList[$key]);continue;
            }

            if(isset($couponsList[$key])){
                $couponsList[$key]['name'] = $coupons['name'];
                isset($couponsList[$key]) ? $couponsList[$key]['reduced_price'] = number_format($couponsList[$key]['reduced_price'], 2, '.', ''): null;
                if($couponsList[$key]['reduced_price'] > $res['price']){
                    $couponsList[$key]['reduced_price'] = number_format($res['price'], 2, '.', '');
                }
            }
        }
        if(count($couponsList) > 0){
            $res['couponsList'] = $couponsList;
        }else{
            $res['couponsList'] = [];
        }
        return $res;
    }

    /**
     * 订单取消
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function cancel()
    {
        $where = [
            'mid'      => $this->member['id'],
            'order_no' => $this->request->post('order_no'),
        ];
        $order = Db::name('StoreOrder')->where($where)->find();
        if (empty($order)) $this->error('待取消的订单不存在，请稍候再试！');
        if (in_array($order['status'], ['1', '2'])) {
            $result = Db::name('StoreOrder')->where($where)->update([
                'status'       => '0',
                'cancel_state' => '1',
                'cancel_at'    => date('Y-m-d H:i:s'),
                'cancel_desc'  => '用户主动取消订单！',
            ]);
            if ($result !== false && \app\store\service\Order::syncStock($order['order_no'])) {
                $this->success('订单取消成功！');
            }
            $this->error('订单取消失败，请稍候再试！');
        }
        $this->error('该订单状态不允许取消哦~');
    }

    /**
     * 订单确认收货
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function confirm()
    {
        $where = [
            'mid'      => $this->member['id'],
            'order_no' => $this->request->post('order_no'),
        ];
        $order = Db::name('StoreOrder')->where($where)->find();
        if (empty($order)) $this->error('待确认的订单不存在，请稍候再试！');
        if (in_array($order['status'], ['4'])) {
            $result = Db::name('StoreOrder')->where($where)->update(['status' => '5']);
            if ($result !== false) $this->success('订单确认成功！');
            $this->error('订单取确认失败，请稍候再试！');
        }
        $this->error('该订单状态不允许确认哦~');
    }

    /**
     * 订单状态统计
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function total()
    {
        $result = Db::name('StoreOrder')->fieldRaw('mid,status,count(1) count')
            ->where(['mid' => $this->mid])->group('status')->select();
        $this->success('获取订单统计记录！', $result);
    }

    public function doPay()
    {
        $orderId = $this->request->param('order_id');
        if(empty($orderId)){
            $this->error('请传入订单ID！');
        }
        $orderInfo = db($this->orderTable)->find($orderId);
        //数据处理
        $orderInfo['price'] = $orderInfo['price_total'];
        $orderInfo['order_sn'] = $orderInfo['order_no'];
        $orderInfo['user_id'] = $orderInfo['mid'];
        $title = db('store_order_list')->where(['order_no' => $orderInfo['order_no']])->value('goods_title');
        $activity_id = db('store_order_list')->where(['order_no' => $orderInfo['order_no']])->value('goods_id');
        $orderInfo['activity_id'] = $activity_id;

        $orderInfo['product_name'] = $title;
        $orderInfo['body'] = '活动:' . $orderInfo['product_name'];

        //优惠券
        $couponsRecordId = $this->request->param('couponsRecordId');
        if(!empty($couponsRecordId)){
            $couponsRecordData = db::table($this->recordTable)->where(['id' => $couponsRecordId]) ->find();
            $coupons = db::table($this->couponsTable)->where(['id' => $couponsRecordData['coupons_id']]) ->find();

            if($couponsRecordData['coupons_type'] == 1 && ($coupons['discount_value'] == -1 || $orderInfo['price'] >= $coupons['discount_value'])){ //优惠券1折扣券，2满x减n,3无条件立减
                $reducedPrice = $orderInfo['price'] * (1-$coupons['discount']/100);

            }else if($couponsRecordData['coupons_type'] == 2 && ($coupons['meet_value'] == -1 || $orderInfo['price'] >= $coupons['meet_value'])){
                $reducedPrice = $coupons['reduction'];
            }else if($couponsRecordData['coupons_type'] == 3){
                $reducedPrice = $coupons['amount'];
            }else{
                $reducedPrice = 0;
            }
            if($reducedPrice > $orderInfo['price']){
                $reducedPrice = number_format($orderInfo['price'], 2, '.', '');
            }

            //更新优惠券和金额
            if(empty($orderInfo['envelope_id'])){
                $upData = [
                    'envelope_id' => $couponsRecordId,
                    'reduced_price' => $reducedPrice,
                ];
                $updateCouponsResult = db($this->orderTable)->where(['id' => $orderId])->update($upData);
                if(!$updateCouponsResult){
                    $this->error('优惠券设置错误！', $updateCouponsResult);
                }
            }else if(!empty($orderInfo['envelope_id']) && $orderInfo['envelope_id'] != $couponsRecordId){
                //防止订单重复，重新生成订单号
                $upData = [
                    'envelope_id' => $couponsRecordId,
                    'reduced_price' => $reducedPrice,
                    'order_no' => Data::uniqidNumberCode(12)
                ];
                $updateCouponsResult = db($this->orderTable)->where(['id' => $orderId])->update($upData);
                if(!$updateCouponsResult){
                    $this->error('优惠券设置错误！2', $updateCouponsResult);
                }else{
                    $orderInfo['order_no'] = $upData['order_no'];
                }
            }
            $reducedPrice = number_format($reducedPrice, 2, '.', '');
            if($reducedPrice == $this->request->param('reduced_price')){
                $orderInfo['envelope_id'] = $couponsRecordId;
                $orderInfo['reduced_price'] = $reducedPrice;
            }else{
                $this->error('优惠券金额错误！', $reducedPrice);
            }
            //重新计算金额
            $orderInfo['price'] = number_format($orderInfo['price'] - $reducedPrice, 2, '.', '');
        }
        if($orderInfo['price'] == 0){ // 无需支付的情况
            $this->update($orderInfo['order_no'], $orderInfo['order_no'], 0);
            $this->success('订单支付成功！', [], 19);
        }

        $wxPay = new WxPay();
        $data = $wxPay->unifiedOrder($orderInfo);
        $this->success('创建预订单成功！', $data);
    }

    /**
     * 订单状态更新
     * @param string $order_no 订单号
     * @param string $pay_no 交易号
     * @param string $pay_price 交易金额
     * @param string $type 支付类型
     * @return boolean
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    private function update($order_no, $pay_no, $pay_price, $type = 'wechat')
    {
        $where = ['order_no' => $order_no, 'pay_state' => '0', 'status' => '2'];
        // 检查订单支付状态
        $order = db($this->orderTable)->where($where)->find();
        if (empty($order)) return false;
        // 更新订单支付状态
        $result = db($this->orderTable)->where($where)->update([
            'pay_type'  => $type, 'pay_no' => $pay_no, 'status' => '3',
            'pay_price' => $pay_price, 'pay_state' => '1', 'pay_at' => date('Y-m-d H:i:s'),
        ]);
        // 调用会员升级机制
//        Order::update($order['order_no']);
        //更新优惠券使用状态
        if(!empty($order['envelope_id'])){
            db($this->recordTable)->where(['id' => $order['envelope_id']])->update(['status' => 2, 'used_time' => date('Y-m-d H:i:s')]);
        }
        return $result !== false;
    }

    public function checkPay()
    {
        $orderId = $this->request->param('id');
        if(empty($orderId)){
            $this->error('请传入订单ID！');
        }
        $orderInfo = db($this->orderTable)->find($orderId);
        //'pay_no' => $pay_no, 'status' => '1','pay_price' => $pay_price, 'pay_status' => '1',
        if($orderInfo['pay_state'] == 1 && $orderInfo['status'] == 3 && !empty($orderInfo['status'])){
            $res['paySuccess'] = true;
            $this->success('支付成功！', $res);
        }
        $res['paySuccess'] = false;
        $this->error('支付失败！', $res);
    }
}